Fix preventBackNavigation crash by clearing the pending activity result - #23150
Closed
nbradbury wants to merge 1 commit into
Closed
Fix preventBackNavigation crash by clearing the pending activity result#23150nbradbury wants to merge 1 commit into
nbradbury wants to merge 1 commit into
Conversation
Activity.finishAffinity() throws IllegalStateException("Can not be called to
deliver a result") when the activity's result code isn't RESULT_CANCELED or it
has result data. openPlayStoreLink() is called from fragments hosted by a wide
range of activities, several of which set a result, so the host frequently has
one pending.
The earlier guard added in #22838 checked isFinishing/isDestroyed, which is
orthogonal to that precondition, so it never suppressed the crash. Clear the
result before finishing instead — we're tearing down the whole task to hand the
user over to Jetpack, so the activity that would have received it is being
finished too. Falls back to finish() for the remaining embedded-activity path.
Sentry: WORDPRESS-ANDROID-3F23, WORDPRESS-ANDROID-3F1V, WORDPRESS-ANDROID-3F3X
Collaborator
Generated by 🚫 Danger |
Contributor
|
|
Contributor
|
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## trunk #23150 +/- ##
=======================================
Coverage 37.84% 37.84%
=======================================
Files 2345 2345
Lines 127511 127514 +3
Branches 17709 17709
=======================================
+ Hits 48255 48258 +3
Misses 75298 75298
Partials 3958 3958 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Contributor
Author
|
Closing this as I'm not convinced Claude found the real problem. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Problem
Activity.finishAffinity()throwsIllegalStateException("Can not be called to deliver a result")when the activity's result code isn'tRESULT_CANCELEDor it has result data.openPlayStoreLink()is called from fragments hosted by a wide range of activities, several of which set a result — so the host can have one pending.#22838 tried to fix this by guarding on
isFinishing/isDestroyed. That's orthogonal to the precondition AOSP actually checks, so it was a no-op: the crash continued through 26.8 and 26.9 and is still present in 27.0 (~239 users across the three Sentry groups). This clears the result before finishing instead, plus afinish()fallback for the remaining embedded-activity throw path.Sentry: WORDPRESS-ANDROID-3F23, WORDPRESS-ANDROID-3F1V, WORDPRESS-ANDROID-3F3X
Verified end to end
Reproduced and fixed on a Pixel 8 / API 35 emulator. Two temporary local edits were needed to reach the code path (neither is in this PR): pointing
JETPACK_PACKAGE_NAMEatcom.jetpack.android.prealphaso a debug Jetpack install counts as installed, and addingrequireActivity().setResult(RESULT_OK, Intent())inJetpackStaticPosterFragment.onViewCreatedto give the host a pending result.Before the fix — WordPress app → Reader tab (JetpackStaticPoster) → "Switch to the Jetpack app":
Same frames as WORDPRESS-ANDROID-3F23 (line numbers differ by the 3 added lines;
Activity.java:7350vs7150is the API level).After the fix, same steps: 0 fatal exceptions, Jetpack in the foreground, 0 remaining WordPress activity records (the task was finished), and Back goes to the launcher rather than WordPress — so the feature's intent is preserved. The
catchfallback did not fire, meaningfinishAffinity()itself succeeded rather than being rescued.Still open
finishAffinity()only finishes activities sharing this affinity, so an activity in a different task that started this one for a result now receivesRESULT_CANCELEDinstead of whatever was pending. That looks right for a "hand the user to Jetpack and tear down the task" flow, but I haven't proven no caller depends on it. This is the part worth reviewing.Activity, sofinishAffinity()is a stub and they cannot exercise this precondition — exactly why Fix Sentry WORDPRESS-ANDROID-3F23: guard preventBackNavigation #22838 shipped green. A real-Activityinstrumented test would catch it, butandroidTestdoesn't compile on trunk in three independent pre-existing places (MySitesPage.ktMatchers.isA<Any>(...)type mismatch,MySitesPage.ktunresolvedR.id.quick_link_item,BaseTest.java:49createComposeRulesignature). I left that test out rather than ship code I couldn't compile.setResultI found on a reachable host is immediately followed byfinish(), which the existingisFinishingguard already short-circuits; the only long-lived one isReaderPostListFragment.onAttach(), which can't run in the WordPress app because the poster replaces the Reader. So something sets a result on these hosts by a path I haven't found. The fix is unconditional and doesn't depend on knowing it, but it means we can't yet write a test that fails for the real reason.Testing
./gradlew :WordPress:testWordPressDebugUnitTest --tests "*ActivityLauncherWrapperTest*"— 8/8 pass. The two new cases assertsetResult(RESULT_CANCELED, null)runs beforefinishAffinity(), and that anIllegalStateExceptionfromfinishAffinity()falls back tofinish()instead of propagating.Follow-ups
androidTestis broken on trunk (see above) — worth fixing independently.ReaderPostListFragment.onAttach()setsRESULT_OKunconditionally on its host, whether or not anything changed.